home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 February: Tool Chest / Dev.CD Feb 94.toast / New System Software Extensions / QuickDraw™ GX v1.0ß2 / Interfaces & Libraries / graphics libraries / font menu library.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-29  |  18.0 KB  |  519 lines  |  [TEXT/MPS ]

  1. /* graphics:    
  2.     gxFont menu library routines
  3.     by Cary Clark, Georgiann Delaney, Michael Fairman, Dave Good, Robert Johnson, Keith McGreggor, Mike Reed, Oliver Steele, David Van Brink, Chris Yerga
  4.     Copyright ©1987 - 1991 Apple Computer, Inc.  All rights reserved.
  5. */
  6.  
  7. #include <Resources.h>
  8. #include <Menus.h>
  9. #include <Memory.h>
  10. #include <ToolUtils.h>
  11. #include <Types.h>
  12. #include <Fonts.h>
  13.  
  14. #include "graphics types.h"
  15. #include "font menu library.h"
  16. #include "font routines.h"
  17. #include "font library.h"
  18. #include "graphics routines.h"
  19.  
  20. #ifdef MacintoshIncludes
  21. #endif
  22.  
  23.  
  24. /*****************************************
  25.  *  Menu manager library routines to handle fonts *
  26.  *****************************************/
  27.  
  28. static long AppendMenuName(MenuHandle menu, long length, unsigned char *name)
  29. {
  30.     name[0] = length < 255 ? length : 255;
  31.     AppendMenu(menu, (void *) "\pfont name");  /*** some full names disable the item */ /* cast for Think C 4.0 */
  32.     SetItem(menu, CountMItems(menu), name);
  33.  
  34.     return length > 255;
  35. }
  36.  
  37. static MenuHandle NewMenuName(short menuID, long length, unsigned char *title)
  38. {
  39.     Str255 str;
  40.  
  41.     str[0] = length < 255 ? length : 255;
  42.     BlockMove(title+1, &str[1], str[0]);
  43.     return NewMenu(menuID, str);
  44. }
  45.  
  46. static int Str255Compare(Str255 a, Str255 b)
  47. {
  48.     int i, minSize = a[0] < b[0] ? a[0] : b[0];
  49.  
  50.     for (i = 1; i < minSize; i++) {
  51.         if (a[i] == b[i])
  52.             continue;
  53.         return a[i] - b[i];
  54.     }
  55.     return a[0] - b[0];
  56. }
  57.  
  58. /*
  59. *       sorts the text, command char, and item mark 
  60. *       this way any submenus will sort with the  item     
  61.  *  THIS SHOULD CALL SOME COOL INTL. SORT ROUTINE
  62.  */
  63. void SortMenu(MenuHandle menu)
  64. {
  65.     short i, j, count = CountMItems(menu);
  66.     
  67.     for (i = 2; i <= count; i++)
  68.         for (j = count; j >= i; --j) {
  69.             short lowercmdChar, uppercmdChar;
  70.             short lowermarkChar, uppermarkChar;
  71.             Str255 lower, upper;
  72.             
  73.             GetItem(menu, j, lower);
  74.             GetItem(menu, j-1, upper);
  75.             GetItemCmd ( menu, j, &lowercmdChar );
  76.             GetItemCmd ( menu, j-1, &uppercmdChar );
  77.             GetItemMark ( menu, j, &lowermarkChar );
  78.             GetItemMark ( menu, j-1, &uppermarkChar );
  79.             
  80.             if (Str255Compare(lower, upper) < 0) {
  81.                 SetItem(menu, j, upper);
  82.                 SetItem(menu, j-1, lower);
  83.                 SetItemCmd ( menu, j, uppercmdChar );
  84.                 SetItemCmd ( menu, j-1, lowercmdChar );
  85.                 SetItemMark ( menu, j, uppermarkChar );
  86.                 SetItemMark ( menu, j-1, lowermarkChar );
  87.             }
  88.         }
  89. }
  90.  
  91. /*
  92.  *  Append a menu with the fonts' full names
  93.  */
  94. long FontMenu(MenuHandle menu)
  95. {
  96.     return FontPlatformMenu(menu, gxNoPlatform, gxNoScript, gxNoLanguage);
  97. }
  98.  
  99. /*
  100.  *  Append a menu with the fonts' full names for fonts that support the specified platform
  101.  */
  102. long FontPlatformMenu(MenuHandle menu, gxFontPlatform platform, gxFontScript script, gxFontLanguage language)
  103. {
  104.     gxFont* fonts;
  105.     long i, count, nameIndex;
  106.     
  107.     count = GXFindFonts(nil, 0, platform, script, language, 0, nil, 1, gxSelectToEnd, 0);
  108.     fonts = (gxFont*)NewPtr(count * sizeof(gxFont));
  109.     GXFindFonts(nil, 0, platform, script, language, 0, nil, 1, count, fonts);
  110.  
  111.     for (i = 0; i < count; i++)
  112.     {   unsigned char *name; 
  113.         long length;
  114.          
  115.         if ((length = GXFindFontName(fonts[i], gxFullFontName, gxMacintoshPlatform, gxRomanScript, gxEnglishLanguage, nil, &nameIndex)) > 0) {
  116.             name = (unsigned char *) NewPtr(length + 1);
  117.             GXGetFontName(fonts[i], nameIndex, nil, nil, nil, nil, &name[1]);
  118.             AppendMenuName(menu, length, name);
  119.             DisposPtr((Ptr) name);
  120.         } 
  121.     }
  122.     DisposPtr((Ptr)fonts);
  123.     SortMenu(menu);
  124.     return count;
  125. }
  126.  
  127. /*
  128.  *  Append a menu with the fonts' family names
  129.  */
  130. long FontFamilyMenu(MenuHandle menu)
  131. {
  132.     return FontFamilyPlatformMenu(menu, gxNoPlatform, gxNoScript, gxNoLanguage);
  133. }
  134.  
  135. long FontFamilyPlatformMenu(MenuHandle menu, gxFontPlatform platform, gxFontScript script, gxFontLanguage language)
  136. {
  137.     gxFont* fonts;
  138.     long i, count;
  139.     
  140.     count = GXFindFonts(nil, gxFamilyFontName, platform, script, language, 0, nil, 1, gxSelectToEnd, nil);
  141.     fonts = (gxFont*)NewPtr(count * sizeof(gxFont));
  142.     GXFindFonts(nil, gxFamilyFontName, platform, script, language, 0, nil, 1, count, fonts);
  143.  
  144.     for (i = 0; i < count; i++)
  145.     {   unsigned char *name;
  146.         long length;
  147.         
  148.         if ((length = GXFindFontName(fonts[i], gxFamilyFontName, gxMacintoshPlatform, gxRomanScript, gxEnglishLanguage, nil, nil)) > 0) {
  149.             name = (unsigned char *) NewPtr(length + 1);
  150.             GXFindFontName(fonts[i], gxFamilyFontName, gxMacintoshPlatform, gxRomanScript, gxEnglishLanguage, &name[1], nil);
  151.             AppendMenuName(menu, length, name);
  152.             DisposPtr((Ptr) name);
  153.         }
  154.     }
  155.     DisposPtr((Ptr)fonts);
  156.     SortMenu(menu);
  157.     return count;
  158. }
  159.  
  160. /*
  161.  *  Create a menu with the given gxFont family's name, filled with the styles available in that family
  162.  */
  163. MenuHandle FontStyleMenu(short menuID, gxFont family)
  164. {
  165.     long i, count = CountFontStyles(family);
  166.     long length;
  167.     MenuHandle menu;
  168.     unsigned char *name;
  169.  
  170.     if ((length = GXFindFontName(family, gxFamilyFontName, gxMacintoshPlatform, gxRomanScript, gxEnglishLanguage, nil, nil)) > 0) {
  171.         name = (unsigned char *) NewPtr(length + 1);
  172.         GXFindFontName(family, gxFamilyFontName, gxMacintoshPlatform, gxRomanScript, gxEnglishLanguage, &name[1], nil);
  173.         menu = NewMenuName(menuID, length, name);
  174.         DisposPtr((Ptr) name);
  175.     } else
  176.         menu = NewMenu(menuID, (void *) "\pNo family name");    /* cast for Think C 4.0 */
  177.  
  178.     for (i = 1; i <= count; i++) {
  179.         gxFont sfnt = FindFontStyle(family, i, 0, 0, 0, 0, nil);
  180.         if ((length = GXFindFontName(sfnt, gxStyleFontName, gxMacintoshPlatform, gxRomanScript, gxEnglishLanguage, nil, nil)) > 0) {
  181.             name = (unsigned char *) NewPtr(length + 1);
  182.             GXFindFontName(sfnt, gxStyleFontName, gxMacintoshPlatform, gxRomanScript, gxEnglishLanguage, &name[1], nil);
  183.             AppendMenuName(menu, length, name);
  184.             DisposPtr((Ptr)name);
  185.         }
  186.     }
  187.     SortMenu(menu);
  188.  
  189.     return menu;
  190. }
  191.  
  192. /*********************************************/
  193. /*                  HierFontMenu                        */
  194. /*                                                  */
  195. /*          the firstHierMenuID let's the application decide        */
  196. /*          what number the heir menu IDs start                     */ 
  197. /*                                                  */
  198. /*********************************************/
  199. short HierFontMenu(MenuHandle theMenu, short firstHierMenuID, fontFilterProc proc, fontMenuAttribute attr)
  200. {
  201.     long        i, count;
  202.     short   heirsUsed = 0;
  203.  
  204.     long            howManyInstances;
  205.     long            howManyVariations;
  206.     gxFontVariation   *variations;
  207.     long            fontNameID;
  208.     
  209.     count = GXFindFonts(nil, 0, 0, 0, 0, 0, nil, 1, gxSelectToEnd, 0);
  210.     for (i = 1; i <= count; i++)
  211.     {   gxFont fontID;
  212.         long length;
  213.  
  214.         GXFindFonts(nil, 0, 0, 0, 0, 0, nil, i, 1, &fontID);
  215.         if (proc && !proc(fontID))
  216.             continue;
  217.  
  218.         if (length = GXFindFontName(fontID, gxFamilyFontName, gxMacintoshPlatform, gxRomanScript, gxEnglishLanguage, nil, nil))
  219.         {
  220.             unsigned char *name;
  221.             Boolean alreadyInMenu = false;
  222.             short numMItem;
  223.             short k;
  224.  
  225.             name = (unsigned char *) NewPtr(length + 1);
  226.             GXFindFontName(fontID, gxFamilyFontName, gxMacintoshPlatform, gxRomanScript, gxEnglishLanguage, &name[1], nil);
  227.             numMItem = CountMItems(theMenu);/*how many items have i already added to the menu*/
  228.             for (k=1; k<= numMItem; k++)    /*check to see if the name is already in the menu*/
  229.             {
  230.                 Str255      str;
  231.                 
  232.                 GetItem (theMenu, k, str);
  233.                 name[0] = length; /*fake str255*/
  234.                 if ( !Str255Compare(str, name) ) 
  235.                     alreadyInMenu = true;
  236.             }
  237.             if (!alreadyInMenu)         /*if not then add it*/
  238.             {
  239.                 MenuHandle hMenu;
  240.                 
  241.                 AppendMenuName(theMenu, length, name);
  242.                 hMenu = FontStyleMenu(heirsUsed + firstHierMenuID, fontID);
  243.                 howManyInstances = (attr & noInstancesFontMenu) ? 0 : GXCountFontInstances(fontID);
  244.                 if( ( (CountMItems(hMenu)) > 1) || (howManyInstances > 0) )/*only add it if it is more than one item*/
  245.                 {   
  246.                     InsertMenu (hMenu, -1);
  247.                     
  248.                     SetItemCmd ( theMenu, numMItem+1, hMenuCmd );
  249.                     SetItemMark ( theMenu, numMItem+1, heirsUsed + firstHierMenuID );
  250.                     heirsUsed ++;
  251.                 }
  252.                 
  253.                 if(howManyInstances)
  254.                 {
  255.                     short m;
  256.                     
  257.                     howManyVariations = GXCountFontVariations(fontID);
  258.                     variations = (gxFontVariation*)NewPtr(sizeof(gxFontVariation) * howManyVariations);
  259.                     
  260.                     AppendMenu(hMenu, (void *) "\p(-" );    /*dotted gxLine*/
  261.                     for(m = 1; m<=howManyInstances; m++)
  262.                     {
  263.                         DisposPtr((Ptr) name);
  264.                         fontNameID = GXGetFontInstance(fontID, m, variations);
  265.                         if ((length = GXFindFontName(fontID, fontNameID, gxMacintoshPlatform, gxRomanScript, gxEnglishLanguage, nil, nil)) > 0) 
  266.                         {
  267.                             name = (unsigned char *) NewPtr(length+1);
  268.                             GXFindFontName(fontID, fontNameID, gxMacintoshPlatform, gxRomanScript, gxEnglishLanguage, &name[1], nil);
  269.                             AppendMenuName(hMenu, length, name);
  270.                         }
  271.                     }
  272.                 }
  273.  
  274.             }
  275.             
  276.             DisposPtr((Ptr) name);
  277.         } 
  278.     }
  279.     SortMenu(theMenu);
  280.     return(heirsUsed);
  281. }
  282.  
  283.  
  284. gxFont DoHierFontMenuCommand(long menuResult, short hierFontMenuID, long *instanceIndex)
  285. {
  286.     short   theItem = LoWord (menuResult);
  287.     short   theMenuID = HiWord (menuResult);
  288.     gxFont        sfnt = 0;
  289.     Str255  str;
  290.     Str255  regStr = "\pRegular";
  291.  
  292.     *instanceIndex = 0;
  293.     
  294.     if( theMenuID == hierFontMenuID)
  295.     {
  296.         GetItem(GetMHandle(theMenuID), theItem, str);
  297.         GXFindFonts(nil, gxFamilyFontName, gxMacintoshPlatform, gxRomanScript, gxEnglishLanguage, str[0], str+1, 1,1,&sfnt);
  298.         GXFindFonts(sfnt, gxStyleFontName, gxMacintoshPlatform, gxRomanScript, gxEnglishLanguage, regStr[0], regStr+1, 1,1,&sfnt);
  299.     }
  300.     else if( theMenuID==0)  /*check if the mouseup was on a family name, if so set sfnt to plain of family???*/
  301.     {
  302.         long mResult = MenuChoice();
  303.         theItem = LoWord (mResult);
  304.         theMenuID = HiWord (mResult);
  305.         if( (theMenuID == hierFontMenuID) && (theItem!=0) )/*could be zero from some other menu*/
  306.         {
  307.             GetItem(GetMHandle(theMenuID), theItem, str);
  308.             GXFindFonts(nil, gxFamilyFontName, gxMacintoshPlatform, gxRomanScript, gxEnglishLanguage, str[0], str+1, 1,1,&sfnt);
  309.             GXFindFonts(sfnt, gxStyleFontName, gxMacintoshPlatform, gxRomanScript, gxEnglishLanguage, regStr[0], regStr+1, 1,1,&sfnt);
  310.         }
  311.     }
  312. //else if( (theMenuID>0) && (theMenuID<235) && (*( (short*)(0x00000a26) ) == hierFontMenuID) )  /*range of hierarchial submenus && owner == hierFontMenuID*/
  313.     else if( (theMenuID>0) && (theMenuID<235) ) /*range of hierarchial submenus && assume owner is hierfontMenuID*/
  314.     {               
  315.         MenuHandle  mh;
  316.         long    index;
  317.         
  318.         mh = GetMHandle(theMenuID);
  319.         MoveHHi((Handle)mh);
  320.         HLock((Handle)mh);
  321.         BlockMove ( (**mh).menuData, str, (**mh).menuData[0]+1 );   /*the title of gxStyle menu is the family name*/
  322.         HUnlock((Handle)mh);
  323.         GXFindFonts(nil, gxFamilyFontName, gxMacintoshPlatform, gxRomanScript, gxEnglishLanguage, str[0], str+1, 1,1,&sfnt);
  324.         
  325.         index = theItem - (CountMItems( mh ) - GXCountFontInstances(sfnt)) ;
  326.         if (index>0)    /*it's an instance*/
  327.             *instanceIndex = index;
  328.         else
  329.         {   /*find by gxFont gxStyle name*/
  330.             gxFont    fontID;
  331.  
  332.             GetItem(mh, theItem, str);
  333.             GXFindFonts(sfnt, gxStyleFontName, gxMacintoshPlatform, gxRomanScript, gxEnglishLanguage, str[0], str+1, 1,1,&fontID);
  334.             sfnt =fontID;
  335.         }
  336.     }           
  337.     HiliteMenu (0);
  338.     return(sfnt);
  339. }
  340.  
  341. short DoHierFontMenuCommandStyle(long menuResult, short hierFontMenuID,gxStyle aStyle, long matchInfo)
  342. {
  343.     short   theItem = LoWord (menuResult);
  344.     short   theMenuID = HiWord (menuResult);
  345.     gxFont        sfnt;
  346.     short   success = true;
  347.     long        instanceIndex;
  348.  
  349.     sfnt = DoHierFontMenuCommand(menuResult,  hierFontMenuID,  &instanceIndex);
  350.     if (sfnt)
  351.     {
  352.         if(matchInfo && ( (theMenuID == hierFontMenuID) || (theItem == 0) ))/*theItem was on the family name*/
  353.         {
  354.             SetMatchingStyle(sfnt, aStyle, matchInfo);
  355.         }
  356.         else/*no gxStyle matching*/
  357.         {
  358.             GXSetStyleFont(aStyle, sfnt);
  359.             if(instanceIndex)
  360.             {
  361.                 long            howManyVariations;
  362.                 gxFontVariation   *variations;
  363.             
  364.                 howManyVariations = GXCountFontVariations(sfnt); 
  365.                 variations = (gxFontVariation*)NewPtr(sizeof(gxFontVariation) * howManyVariations);
  366.                 GXGetFontInstance(sfnt, instanceIndex, variations);
  367.                 GXSetStyleFont(aStyle, sfnt);
  368.                 GXSetStyleFontVariations(aStyle, howManyVariations, variations);
  369.                 DisposePtr((Ptr)variations);
  370.             }
  371.             else
  372.                 GXSetStyleFontVariations(aStyle, 0, nil);
  373.         }
  374.     }
  375.     else    /*not our menu*/
  376.         success = false;
  377.     
  378.     HiliteMenu (0);
  379.     return(success);
  380. }
  381.  
  382. short DoHierFontMenuCommandShape(long menuResult, short hierFontMenuID,gxShape aShape)
  383. {
  384.     short   theItem = LoWord (menuResult);
  385.     short   theMenuID = HiWord (menuResult);
  386.     gxFont        sfnt;
  387.     short   success = true;
  388.     long        instanceIndex;
  389.  
  390.     sfnt = DoHierFontMenuCommand(menuResult,  hierFontMenuID,  &instanceIndex);
  391.     if (sfnt)
  392.     {
  393.         GXSetShapeFont(aShape, sfnt);
  394.         if(instanceIndex)
  395.         {
  396.             long            howManyVariations;
  397.             gxFontVariation   *variations;
  398.         
  399.             howManyVariations = GXCountFontVariations(sfnt); 
  400.             variations = (gxFontVariation*)NewPtr(sizeof(gxFontVariation) * howManyVariations);
  401.             GXGetFontInstance(sfnt, instanceIndex, variations);
  402.             GXSetShapeFont(aShape, sfnt);
  403.             GXSetShapeFontVariations(aShape, howManyVariations, variations);
  404.             DisposePtr((Ptr)variations);
  405.         }
  406.         else
  407.             GXSetShapeFontVariations(aShape, 0, nil);
  408.     }
  409.     else    /*not our menu*/
  410.         success = false;
  411.     
  412.     HiliteMenu (0);
  413.     return(success);
  414. }
  415.  
  416. gxFont QDToFont(long fondID, long styleBits)
  417. {
  418.     short resID;
  419.     OSType resType;
  420.     Str255 resName;
  421.     FMInput inputRecord;
  422.     FMOutput outputRecord;
  423.  
  424.     inputRecord.family = fondID;
  425.     inputRecord.size = 2048;
  426.     inputRecord.face = styleBits;
  427.     inputRecord.needBits = false;
  428.     inputRecord.device = 0;
  429.     inputRecord.numer = inputRecord.denom = *(Point*)0x00010001;
  430.     outputRecord = *FMSwapFont(&inputRecord);
  431.     
  432.     GetResInfo(outputRecord.fontHandle, &resID, &resType, resName);
  433.     if (!ResError() && resType == 'sfnt')
  434.     {   long i, count = GXFindFonts(nil, 0, 0, 0, 0, 0, nil, 1, gxSelectToEnd, nil);
  435.     
  436.         for (i = 1; i <= count; i++)
  437.         {   gxFont fontID;
  438.             gxFontStorageReference reference;
  439.  
  440.             GXFindFonts(nil, 0, 0, 0, 0, 0, nil, i, 1, &fontID);
  441.             if (GXGetFont(fontID, &reference, nil) == gxResourceFontStorage && outputRecord.fontHandle == (Handle)reference)
  442.                 return fontID;
  443.         }
  444.     }
  445.     return nil;
  446. }
  447.  
  448. long FontToQD(gxFont fontID, long* styleBits)
  449. {
  450.     short resID, i, count;
  451.     OSType resType;
  452.     Str255 resName;
  453.     Handle sfnt;
  454.  
  455.     if (GXGetFont(fontID, (gxFontStorageReference*)&sfnt, nil) != gxResourceFontStorage)
  456.         goto NOT_FOUND;
  457.     GetResInfo(sfnt, &resID, &resType, resName);
  458.     if (ResError())
  459.         goto NOT_FOUND;
  460.  
  461.     count = CountResources('FOND');
  462.     for (i = 1; i <= count; i++)
  463.     {   Handle fond = GetIndResource('FOND', i);
  464.  
  465.         if (!ResError() && fond && *fond)
  466.         {   short* sp = (short*)(*fond + sizeof(FamRec));
  467.             int entries = *sp++;
  468.             
  469.             for (; entries >= 0; --entries)
  470.             {   if (*sp == 0 && sp[2] == resID)
  471.                 {   if (styleBits)
  472.                         *styleBits = sp[1];
  473.                     GetResInfo(fond, &resID, &resType, resName);
  474.                     return resID;
  475.                 }
  476.                 sp += 3;        /* three elements in the FAT */
  477.             }
  478.         }
  479.     }
  480. NOT_FOUND:
  481.     return 0;
  482. }
  483.  
  484. void FontFeatureMenu(MenuHandle menu, gxFont fontID, short firstHierMenuID)
  485. {
  486.     long i, featureCount;
  487.     gxFontName nameID;
  488.     Str255 name;
  489.  
  490.     featureCount = GXCountFontFeatures(fontID);
  491.     for (i = 1; i <= featureCount; i++)
  492.     {   long settingCount;
  493.         
  494.         nameID = GXGetFontFeature(fontID, i, nil, &settingCount, nil, nil);
  495.         FindFontPName(fontID, nameID, name);
  496.         AppendMenu(menu, (void *) name);
  497.         if (settingCount > 1)
  498.         {   long j;
  499.             MenuHandle hierMenu;
  500.             gxFontFeatureSetting* settings;
  501.  
  502.             hierMenu = NewMenu(firstHierMenuID, name);
  503.             InsertMenu(hierMenu, -1);
  504.             SetItemCmd(menu, i, hMenuCmd );
  505.             SetItemMark(menu, i, firstHierMenuID);
  506.             firstHierMenuID++;
  507.     
  508.             settings = (gxFontFeatureSetting*)NewPtr(settingCount * sizeof(gxFontFeatureSetting));
  509.             GXGetFontFeature(fontID, i, nil, nil, settings, nil);
  510.             for (j = 0; j < settingCount; j++)
  511.             {   FindFontPName(fontID, settings[j].nameID, name);
  512.                 AppendMenu(hierMenu, (void *) name);
  513.             }
  514.             DisposPtr((Ptr)settings);
  515.         }
  516.     }
  517. }
  518.  
  519.